﻿#include "stdafx.h"
#include "./luaregistration.h"
#include "./luaex.h"

Registration::Registration()
: next(NULL)
{
}

Registration::~Registration()
{
}

void Registration::Register(lua_State* luaState, bool bGlobal) const
{
    if (next)
    {
        next->Register(luaState, bGlobal);
    }
}

int ScriptRegistration::s_ref = -1;

ScriptRegistration::ScriptRegistration(const char * script, const char * chunkname)
: m_sciprt(script)
, m_chunkname(chunkname)
{
}

ScriptRegistration::~ScriptRegistration()
{
}

void ScriptRegistration::Register(lua_State* luaState, bool bGlobal) const
{
    const char * chunkname = m_chunkname ? m_chunkname : m_sciprt;
    if (luaL_loadbuffer(luaState, m_sciprt, strlen(m_sciprt), chunkname))
    {
        //error
        //LuaEx::ErrorFunc();
		const char * pTest = lua_tostring(luaState, -1);
		::OutputDebugStringA(pTest);
        return;
    }

    if (!bGlobal)
    {
        if (!lua_getmetatable(luaState, -2))
        {
            GetModuleMeta(luaState);
            lua_setmetatable(luaState, -3);
        }
        else
        {
            lua_pop(luaState, 1);
        }

        lua_pushvalue(luaState, -2);
        lua_setfenv(luaState, -2);
    }

    if (0 != lua_pcall(luaState, 0, 0, 0))
    {
        //error
        //LuaEx::ErrorFunc();
    }

    Registration::Register(luaState, bGlobal);
}

void ScriptRegistration::GetModuleMeta(lua_State* luaState)
{
    if (s_ref == -1)
    {
        lua_newtable(luaState);
        lua_pushvalue(luaState, -1);
        s_ref = luaL_ref(luaState, LUA_REGISTRYINDEX);

        lua_pushstring(luaState, "__index");
        lua_pushvalue(luaState, LUA_GLOBALSINDEX);
        lua_settable(luaState, -3);
    }
    else
    {
        lua_rawgeti(luaState, LUA_REGISTRYINDEX, s_ref);
    }
}

ModuleRegistration::ModuleRegistration(const char * modulename)
: m_modulename(modulename)
{
}

ModuleRegistration::~ModuleRegistration()
{
}

void ModuleRegistration::Register(lua_State* luaState, bool bGlobal) const
{
	if (m_modulename)
	{
		lua_getglobal(luaState, m_modulename);

		//delete global module
		lua_pushnil(luaState);
		lua_setglobal(luaState, m_modulename);

		if (bGlobal)
		{
			lua_setglobal(luaState, m_modulename);
		}
		else
		{
			lua_pushstring(luaState, m_modulename);
			lua_pushvalue(luaState, -2);
			lua_settable(luaState, -4);
			lua_pop(luaState, 1);
		}
	}

	Registration::Register(luaState, bGlobal);
}

LuaFunctionRegistration::LuaFunctionRegistration(const char * name, lua_CFunction func)
: m_name(name)
, m_func(func)
{
}

LuaFunctionRegistration::~LuaFunctionRegistration()
{
}

void LuaFunctionRegistration::Register(lua_State* luaState, bool bGlobal) const
{
    if (bGlobal)
    {
        lua_pushcfunction(luaState, m_func);
        lua_setglobal(luaState, m_name);
    }
    else
    {
        lua_pushstring(luaState, m_name);
        lua_pushcfunction(luaState, m_func);
        lua_settable(luaState, -3);
    }

    Registration::Register(luaState, bGlobal);
}
